﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Threading;
using System.Net;
using System.Drawing;
using System.Windows.Forms;

namespace NewAI.Client
{
    public sealed class ServerConnector
    {
        private Socket socket;
        private Thread receiveDataThread;

        /// <summary>
        /// 当有消息接收的时候会触发该消息
        /// </summary>
        public event EventHandler<ServerConnectorEventArgs> OnReceiveData;

        /// <summary>
        /// 当Socket连接出现异常时会触发该消息
        /// </summary>
        public event EventHandler<ServerConnectorEventArgs> OnSocketException;

        private ServerConnector() { }


        /// <summary>
        /// 连接服务器
        /// </summary>
        /// <param name="host"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        /// <exception cref="SocketException"></exception>
        public static ServerConnector Connect(string host = "127.0.0.1", int port = 6000)
        {
            ServerConnector client = new ServerConnector();
            client.socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            client.socket.Connect(host, port);
            client.StartReceiveDataThread();
            return client;
        }

        public void Close()
        {
            if (receiveDataThread != null && receiveDataThread.IsAlive == true)
                receiveDataThread.Abort();
            if (socket != null)
                socket.Close();
        }

        public void Send(byte[] data)
        {
            socket.Send(data);
        }

        /// <summary>
        /// 发送前面带有字符传长度（5位数，高位不足自动补0）的文本
        /// </summary>
        /// <param name="data"></param>
        public void Send(string data)
        {
            string lenStr = data.Length.ToString();
            for (int i = lenStr.Length; i < 5; i++)
                lenStr = "0" + lenStr;
            try
            {
                socket.Send(Encoding.UTF8.GetBytes(lenStr + data));
            }
            catch (Exception ex)
            {
                CallOnSocketException(ex.Message);
            }
        }

        private void StartReceiveDataThread()
        {
            receiveDataThread = new Thread(new ThreadStart(ReceiveData));
            receiveDataThread.Start();
        }

        private void ReceiveData()
        {
            byte[] buffer = new byte[99999];
            int length = 0;
            while (true)
            {
                try
                {
                    length = socket.Receive(buffer);
                    if (length > 0)
                        CallOnReceiveData(Encoding.UTF8.GetString(buffer, 0, length));
                }
                catch (Exception ex)
                {
                    CallOnSocketException(ex.Message);
                }
            }
        }

        private void CallOnSocketException(string msg)
        {
            if (OnSocketException == null)
                return;
            Delegate[] addDelegates = OnSocketException.GetInvocationList();
            foreach (EventHandler<ServerConnectorEventArgs> item in addDelegates)
                item.BeginInvoke(null, new ServerConnectorEventArgs(msg), null, null);
        }

        private void CallOnReceiveData(string msg)
        {
            if (OnReceiveData == null)
                return;
            Delegate[] addDelegates = OnReceiveData.GetInvocationList();
            foreach (EventHandler<ServerConnectorEventArgs> item in addDelegates)
                item.BeginInvoke(null, new ServerConnectorEventArgs(msg), null, null);
        }
    }
}
